package co.yixiang.yshop.module.system.service.backuprecord;

import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.system.controller.admin.backuprecord.vo.BackupPageReqVO;
import co.yixiang.yshop.module.system.controller.admin.backuprecord.vo.BackupRecordRespVO;
import co.yixiang.yshop.module.system.convert.backuprecord.BackupRecordConvert;
import co.yixiang.yshop.module.system.dal.dataobject.backup.BackupRecordDO;
import co.yixiang.yshop.module.system.dal.dataobject.user.AdminUserDO;
import co.yixiang.yshop.module.system.dal.mysql.backuprecord.BackupRecordMapper;
import co.yixiang.yshop.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.system.enums.ErrorCodeConstants.BACKUP_MANY;

/**
 * 品牌 Service 实现类
 *
 * @author yshop
 */
@Service
@Slf4j
@Validated
public class BackupRecordServiceImpl extends ServiceImpl<BackupRecordMapper, BackupRecordDO> implements BackupRecordService {

    @Resource
    private BackupRecordMapper backupRecordMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AdminUserService adminUserService;


    private static final String orderCountKey = "yshop_order_count_cache:*";

    private static final String orderAdminCountKey = "yshop_admin_order_count_cache:*";

    @Override
    public PageResult<BackupRecordRespVO> backupPageList(BackupPageReqVO pageVO) {
        PageResult<BackupRecordDO> pageResult = this.baseMapper.selectPage(pageVO);
        if (pageResult.getTotal() > 0) {
            List<Long> ids = new ArrayList<>();
            pageResult.getList().forEach(record -> {
                        ids.add(Long.parseLong(record.getCreator()));
                        if (!StringUtils.isEmpty(record.getUpdater())) {
                            ids.add(Long.parseLong(record.getUpdater()));
                        }
                    }
            );
            Map<Long, String> nameMap = adminUserService.getUserList(ids).stream()
                    .collect(Collectors.toMap(AdminUserDO::getId, AdminUserDO::getUsername));
            PageResult<BackupRecordRespVO> page = BackupRecordConvert.INSTANCE.convertPage(pageResult);
            page.getList().forEach(resp -> {
                resp.setCreatorName(nameMap.get(Long.parseLong(resp.getCreator())));
                if (!StringUtils.isEmpty(resp.getUpdater())) {
                    resp.setUpdaterName(nameMap.get(Long.parseLong(resp.getUpdater())));
                }
            });
            return page;
        } else {
            return PageResult.empty();
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void backup() {
        BackupRecordDO last = backupRecordMapper.selectOne(new LambdaQueryWrapper<BackupRecordDO>().orderByDesc(
                BackupRecordDO::getId
        ).last("limit 1"));
        if (last != null) {
            if (last.getCreateTime().plusMinutes(5).isAfter(LocalDateTime.now())) {
                throw exception(BACKUP_MANY);
            }
        }
        //druid空闲连接池关闭之后 第一次执行失败 第二次成功
        try {
            this.baseMapper.backup();
        } catch (Exception e) {
            log.info("第一次备份异常,重试中。。。");
        }
        this.baseMapper.backup();
        BackupRecordDO backupRecordDO = new BackupRecordDO();
        backupRecordDO.setCreateTime(LocalDateTime.now());
        this.baseMapper.insert(backupRecordDO);
        log.info("======备份成功=====");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void revertBackup() {
        BackupRecordDO backupRecordDO = backupRecordMapper.selectOne(new LambdaQueryWrapper<BackupRecordDO>().orderByDesc(
                BackupRecordDO::getId
        ).last("limit 1"));
        if (backupRecordDO != null) {
            if (backupRecordDO.getUpdateTime().plusMinutes(5).isAfter(LocalDateTime.now()) &&
                    !backupRecordDO.getCreateTime().isEqual(backupRecordDO.getUpdateTime())) {
                throw exception(BACKUP_MANY);
            }
        }
        try {
            this.baseMapper.revertBackup();
        } catch (Exception e) {
            log.info("第一次还原备份异常,重试中。。。");
        }
        this.baseMapper.revertBackup();
        assert backupRecordDO != null;
        backupRecordDO.setUpdateTime(LocalDateTime.now());
        this.baseMapper.updateById(backupRecordDO);
        //清除redis信息
        Set<String> orderCountKeys = stringRedisTemplate.keys(orderCountKey);
        Set<String> orderAdminCountKeys = stringRedisTemplate.keys(orderAdminCountKey);
        assert orderCountKeys != null;
        stringRedisTemplate.delete(orderCountKeys);
        assert orderAdminCountKeys != null;
        stringRedisTemplate.delete(orderAdminCountKeys);
        log.info("======还原备份成功=====");
    }
}
